#include "qtvplugin_orbit.h"
#include <QBrush>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QLibraryInfo>
#include <QMap>
#include <QMessageBox>
#include <QMutex>
#include <QPainter>
#include <QPen>
#include <QSettings>
#include "../geocalc/geocalc.h"
#include "../qtviewer_planetosm/interface_utils.h"
#include "ui_qtvplugin_orbit.h"
#include <assert.h>
#include <math.h>

QMutex mutex_instances; //!This QMutex protect map_instances and count_instances
QMap<viewer_interface *, qtvplugin_orbit * >
map_instances; //!Mapping viewer_interface to qtvplugins
QMap<QString, int >
count_instances; //!a counter for instances numbering

qtvplugin_orbit::qtvplugin_orbit(QWidget *parent)
	: QWidget(parent)
	, m_nInstance(0)
	, ui(new Ui::qtvplugin_orbit)
{
	ui->setupUi(this);
	m_pVi = 0;
	m_bVisible = true;
	m_bActive = false;
	m_nTraceTimer = startTimer(1000);
}

qtvplugin_orbit::~qtvplugin_orbit()
{
	delete ui;
}
void qtvplugin_orbit::load_retranslate_UI()
{
	ui->retranslateUi(this);
}

layer_interface *qtvplugin_orbit::load_initial_plugin(QString strSLibPath,
													  viewer_interface *ptrviewer)
{
	//!In this instance, we will see how to create a new instance for each ptrviewer
	qtvplugin_orbit *instance = 0;

	//!1.Check whether there is already a instance for ptrviewer( viewer_interface)
	mutex_instances.lock();
	if (map_instances.empty() == true) {
		map_instances[ptrviewer] = this;
		instance = this;
	} else if (map_instances.contains(ptrviewer) == false) {
		//Create a new instance for ptrviewer
		instance = new qtvplugin_orbit;
		map_instances[ptrviewer] = instance;
	} else
		instance = map_instances[ptrviewer];
	mutex_instances.unlock();

	//!2.if the instance correspones to this, do init operations.
	if (instance == this) {
		QFileInfo info(strSLibPath);
		m_SLLibName = info.completeBaseName();
		m_SLLibPath = strSLibPath;

		m_pVi = ptrviewer;

		mutex_instances.lock();
		m_nInstance = ++count_instances[m_SLLibName];
		mutex_instances.unlock();

		loadTranslation();
		load_ini();
	}
	//!3.if the instance not correspones to this, call the instances' load_initial_plugin instead.
	else {
		layer_interface *ret = instance->load_initial_plugin(strSLibPath, ptrviewer);
		assert(ret == instance);
	}
	init_tle_mod();
	init_trace_mod();
	return instance;
}

bool qtvplugin_orbit::loadTranslation()
{
	bool res = false;
	//Trans
	QCoreApplication *app = QCoreApplication::instance();
	if (app && m_nInstance == 1) {
		QString strTransLocalFile = ":/qtvplugin_orbit_" + QLocale::system().name() + ".qm";
		if (true == pluginTranslator.load(strTransLocalFile)) {
			QTVOSM_DEBUG("Load translationfile") << "\n\t" << strTransLocalFile << " Succeeded.";
			app->installTranslator(&pluginTranslator);
			ui->retranslateUi(this);
			res = true;
		} else
			QTVOSM_WARNING("Load translationfile") << "\n\t" << strTransLocalFile << " Not Found.";
	}
	return res;
}

QWidget *qtvplugin_orbit::load_prop_window()
{
	return this;
}

void qtvplugin_orbit::cb_paintEvent(QPainter *pImage) {}

bool qtvplugin_orbit::is_visible()
{
	return m_bVisible;
}

void qtvplugin_orbit::set_visible(bool vb)
{
	m_bVisible = vb;
}

QString qtvplugin_orbit::get_name()
{
	QString strName = m_SLLibName.mid(10);
	if (m_SLLibName.left(3) == "lib")
		strName = m_SLLibName.mid(13);
	if (strName.length())
		return strName /*+ QString("%1").arg(m_nInstance)*/;
	else
		return "orbit";
}
bool qtvplugin_orbit::is_active()
{
	return m_bActive;
}

void qtvplugin_orbit::set_active(bool ab)
{
	m_bActive = ab;
}

void qtvplugin_orbit::set_name(QString /*vb*/) {}

bool qtvplugin_orbit::cb_event(const QMap<QString, QVariant> para)
{
	if (m_pVi == 0)
		return false;
	return false;
}
bool qtvplugin_orbit::cb_mouseMoveEvent(QMouseEvent *e)
{
	if (m_pVi == 0)
		return false;
	if (m_bVisible == true) {
	}
	if (m_bActive == false)
		return false;

	return false;
}

bool qtvplugin_orbit::cb_mousePressEvent(QMouseEvent *e)
{
	if (m_pVi == 0)
		return false;
	if (m_bActive == false)
		return false;
	if (e->buttons() & Qt::LeftButton) {
	} else if (e->buttons() & Qt::RightButton) {
	}
	return false;
}

QMap<QString, QVariant>
qtvplugin_orbit::call_func(	const QMap<QString, QVariant> &paras)
{
	QMap<QString, QVariant>	res;

	return /*std::move*/ (res);
}

QString qtvplugin_orbit::ini_file()
{
	if (m_SLLibPath.size())
		return m_SLLibPath + QString("%1").arg(m_nInstance) + ".ini";
	else
		return QCoreApplication::applicationFilePath() + QString("/orbit%1.ini").arg(m_nInstance);
}
void qtvplugin_orbit::load_ini()
{
	QSettings settings(ini_file(), QSettings::IniFormat);
	ui->lineEdit_orbit_tle_file->setText(settings.value("orbit_gui/lineEdit_orbit_tle_file",ui->lineEdit_orbit_tle_file->text()).toString());
	ui->lineEdit_orbit_tle_db->setText(settings.value("orbit_gui/lineEdit_orbit_tle_db",ui->lineEdit_orbit_tle_db->text()).toString());
	ui->lineEdit_orbit_tledb_filter->setText(settings.value("orbit_gui/lineEdit_orbit_tledb_filter",ui->lineEdit_orbit_tledb_filter->text()).toString());
	ui->dateTimeEdit_orbit_time->setDateTime(settings.value("orbit_gui/dateTimeEdit_orbit_time",ui->dateTimeEdit_orbit_time->dateTime()).toDateTime());
	ui->checkBox_track->setChecked(settings.value("orbit_gui/checkBox_track",ui->checkBox_track->isChecked()).toBool());
	ui->lineEdit_orbit_trace_filter->setText(settings.value("orbit_gui/lineEdit_orbit_trace_filter",ui->lineEdit_orbit_trace_filter->text()).toString());
	ui->spinBox_minEL->setValue(settings.value("orbit_gui/spinBox_minEL",ui->spinBox_minEL->value()).toInt());
	ui->doubleSpinBox_orbit_ob_alt->setValue(settings.value("orbit_gui/doubleSpinBox_orbit_ob_alt",ui->doubleSpinBox_orbit_ob_alt->value()).toDouble());
	ui->doubleSpinBox_orbit_ob_lon->setValue(settings.value("orbit_gui/doubleSpinBox_orbit_ob_lon",ui->doubleSpinBox_orbit_ob_lon->value()).toDouble());
	ui->doubleSpinBox_orbit_ob_lat->setValue(settings.value("orbit_gui/doubleSpinBox_orbit_ob_lat",ui->doubleSpinBox_orbit_ob_lat->value()).toDouble());
	ui->spinBox_orbit_maxAge->setValue(settings.value("orbit_gui/spinBox_orbit_maxAge",ui->spinBox_orbit_maxAge->value()).toInt());
}

void qtvplugin_orbit::save_ini()
{
	QSettings settings(ini_file(), QSettings::IniFormat);
	settings.setValue("orbit_gui/lineEdit_orbit_tle_file",ui->lineEdit_orbit_tle_file->text());
	settings.setValue("orbit_gui/lineEdit_orbit_tle_db",ui->lineEdit_orbit_tle_db->text());
	settings.setValue("orbit_gui/lineEdit_orbit_tledb_filter",ui->lineEdit_orbit_tledb_filter->text());
	settings.setValue("orbit_gui/dateTimeEdit_orbit_time",ui->dateTimeEdit_orbit_time->dateTime());
	settings.setValue("orbit_gui/checkBox_track",ui->checkBox_track->isChecked());
	settings.setValue("orbit_gui/lineEdit_orbit_trace_filter",ui->lineEdit_orbit_trace_filter->text());
	settings.setValue("orbit_gui/spinBox_minEL",ui->spinBox_minEL->value());
	settings.setValue("orbit_gui/doubleSpinBox_orbit_ob_alt",ui->doubleSpinBox_orbit_ob_alt->value());
	settings.setValue("orbit_gui/doubleSpinBox_orbit_ob_lon",ui->doubleSpinBox_orbit_ob_lon->value());
	settings.setValue("orbit_gui/doubleSpinBox_orbit_ob_lat",ui->doubleSpinBox_orbit_ob_lat->value());
	settings.setValue("orbit_gui/spinBox_orbit_maxAge",ui->spinBox_orbit_maxAge->value());
}

void qtvplugin_orbit::timerEvent(QTimerEvent * evt)
{
	if (evt->timerId()==m_nTraceTimer )
	{
		if (!m_bool_trace_caling)
		{

			if (ui->checkBox_track->isChecked())
			{
				QDateTime utcNow = QDateTime::currentDateTimeUtc();
				ui->dateTimeEdit_orbit_time->setDateTime(utcNow);
			}
			if (m_needUpdate)
			{
				m_needUpdate = false;
				//Select nearest tle
				confirm_trace_conn(true);
				//Cal the pos and speed for each tracing sat.
				cal_sat_pv();
			}
		}
	}
	return QWidget::timerEvent(evt);
}

void qtvplugin_orbit::on_toolButton_orbit_tle_db_clicked()
{
	QSettings settings(ini_file(), QSettings::IniFormat);
	QDir dir_app(QCoreApplication::applicationDirPath());
	QString last_dbdir = settings.value("orbit_db/dbdir", "./").toString();
	last_dbdir = dir_app.absoluteFilePath(last_dbdir);
	QString fileName = QFileDialog::getSaveFileName(this,
													tr("Select SQLite DB"),
													last_dbdir,
													"SQLite DB (*.db);;All files (*.*)");
	if (fileName.length() > 2)
	{
		QFileInfo info(fileName);
		QString dirCurr = dir_app.relativeFilePath(info.absolutePath());
		settings.setValue("orbit_db/dbdir", dirCurr);
		fileName = dir_app.relativeFilePath(fileName);
		ui->lineEdit_orbit_tle_db->setText(fileName);
		save_ini();
	}
}

void qtvplugin_orbit::on_pushButton_orbit_refresh_clicked()
{
	save_ini();
	m_pTleMod->clear();
	m_pTleModDetail->clear();
	const QString dbname = ini_file();
	if (QSqlDatabase::contains(dbname))
	{
		QSqlDatabase::database(dbname).close();
		QSqlDatabase::removeDatabase(dbname);
	}
	confirm_tle_conn(true);
	confirm_trace_conn(true);
}

